package org.codesamples.hibernate.flush;

import static junit.framework.Assert.assertEquals;

import org.codesamples.hibernate.base.HibernateUtil;
import org.codesamples.hibernate.model.onetoone.Father;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class HibernateWithTransaction {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		HibernateWithTransaction hibernateWithTransaction = new HibernateWithTransaction();
		
		System.out.println("================= present In Session And Database =================");
		hibernateWithTransaction.presentInSessionAndDatabase();
		
		System.out.println("================= present In Session And Not In Database Without Flush =================");
		hibernateWithTransaction.presentInSessionAndNotInDatabaseWithoutFlush();
		
		System.out.println("================= present In Session And Not In Database With Flush =================");
		hibernateWithTransaction.presentInSessionAndNotInDatabaseWithFlush();
		
		System.out.println("================= present In Session And Not In Database With Flush And Clear =================");
		hibernateWithTransaction.presentInSessionAndNotInDatabaseWithFlushAndClear();
		
	}
	
	public void presentInSessionAndDatabase() {		
		Session session = HibernateUtil.getSession();
		
		Transaction transaction = session.beginTransaction();
		
		try {
			
			Father father = new Father();
			father.setName("jeorge 1");
			session.save(father);
			
			/* check data in session */
			Father fatherInSession = (Father) session.get(Father.class, 1);
			assertEquals(fatherInSession.getId(), 1);
			assertEquals(fatherInSession.getName(), "jeorge 1");

			/* check data in database */
			
			try {
				String dbFatherName = HibernateUtil.getData("select name from Father Where Id = 1");
				System.out.println("fatherInSession :: " + fatherInSession.getName());
				System.out.println("dbFatherName :: " + dbFatherName);				
			}catch(Exception ex) {
				ex.printStackTrace();
			}
			
			transaction.commit();
		}catch(Exception ex) {
			ex.printStackTrace();
			if(transaction.isActive()) {
				transaction.rollback();
			}
		}
		
		System.out.println("------------------------");
		
		String dbFatherName = HibernateUtil.getData("select name from Father Where Id = 1");		
		System.out.println("dbFatherName :: " + dbFatherName);
		
	}	
	
	public void presentInSessionAndNotInDatabaseWithoutFlush() {
		Session session = HibernateUtil.getSession();

		Transaction transaction = session.beginTransaction();
		 
		try {
		
			Father father = new Father();
			father.setName("jeorge 2");
			session.save(father);
			
			/* change the name of father entity (applicable only in session will not be updated in database until flush/update) */
			father.setName("jeorge 2 changed");
					
			/* check data in session */
			Father fatherInSession = (Father) session.get(Father.class, 2);		
			assertEquals(fatherInSession.getId(), 2);
			assertEquals(fatherInSession.getName(), "jeorge 2 changed");
			
			/* check data in database */
			
			try {
				String dbFatherName = HibernateUtil.getData("select name from Father Where Id = 1");
				System.out.println("fatherInSession :: " + fatherInSession.getName());
				System.out.println("dbFatherName :: " + dbFatherName);				
			}catch(Exception ex) {
				ex.printStackTrace();
			}
			
			transaction.commit();
		}catch(Exception ex) {
			ex.printStackTrace();
			if(transaction.isActive()) {
				transaction.rollback();
			}
		}
	}
	
	public void presentInSessionAndNotInDatabaseWithFlush() {
		Session session = HibernateUtil.getSession();

		Transaction transaction = session.beginTransaction();
		 
		try {
			Father father = new Father();
			father.setName("jeorge 3");
			session.save(father);
			
			/* change the name of father entity (applicable only in session will not be updated in database until flush/update) */
			father.setName("jeorge 3 changed");
					
			session.flush();
			
			//father.setName("jeorge 2 changed again");		
			//session.clear();
			
			/* check data in session */
			Father fatherInSession = (Father) session.get(Father.class, 3);		
			assertEquals(fatherInSession.getId(), 3);
			assertEquals(fatherInSession.getName(), "jeorge 3 changed");
			
			/* check data in database */
			
			try {
				String dbFatherName = HibernateUtil.getData("select name from Father Where Id = 1");
				System.out.println("fatherInSession :: " + fatherInSession.getName());
				System.out.println("dbFatherName :: " + dbFatherName);				
			}catch(Exception ex) {
				ex.printStackTrace();
			}
			
			transaction.commit();
		}catch(Exception ex) {
			ex.printStackTrace();
			if(transaction.isActive()) {
				transaction.rollback();
			}
		}
	}
	
	public void presentInSessionAndNotInDatabaseWithFlushAndClear() {
		Session session = HibernateUtil.getSession();
		Transaction transaction = session.beginTransaction();
		 
		try {
			Father father = new Father();
			father.setName("jeorge 4");
			session.save(father);
	
			/* change the name of father entity (applicable only in session will not be updated in database until flush/update) */
			father.setName("jeorge 4 changed");
	
			session.flush();
			
			father.setName("jeorge 4 changed again");
			
			session.clear();
			
			/* check data in session */
			Father fatherInSession = (Father) session.get(Father.class, 4);		
			assertEquals(fatherInSession.getId(), 4);
			assertEquals(fatherInSession.getName(), "jeorge 4 changed");
			
			/* check data in database */
			
			try {
				String dbFatherName = HibernateUtil.getData("select name from Father Where Id = 1");
				System.out.println("fatherInSession :: " + fatherInSession.getName());
				System.out.println("dbFatherName :: " + dbFatherName);				
			}catch(Exception ex) {
				ex.printStackTrace();
			}
			
			transaction.commit();
		}catch(Exception ex) {
			ex.printStackTrace();
			if(transaction.isActive()) {
				transaction.rollback();
			}
		}
	}
}
